#include "GameBoard.h"
#include <windows.h>   // WinApi header
#include <iostream>
#include <cstdlib>
#include <iomanip>	//For formatting the stats output

using std::cout;
using std::cin;
using std::endl;
using std::fixed;
using std::setprecision;
const int YES = 1;
const int NO = 2;

//Function to check numerical inputs
int intValidationInput(int);

int main()
{
	HANDLE mhConsole = GetStdHandle(STD_OUTPUT_HANDLE);
	int wins;	//The total wins in the course of playtime
	int runs;	//To keep track of total complete run throughs in a user's playtime
	int boardSelection = 0;	//To hold initial board size choice.
	int boardChoice = 0;		//To hold the verified board choice.
	int gameType = 0;	//To hold the user's choice of game type.
	int playAgainChoice = 0;	//To see if they want to play again.

	//These are all bools to verify input and exit menus. They are set to false at the start of their respective loops.
	bool gameTypeMenu;
	bool playAgainMenu;
	bool boardSizeMenu;
	bool innerPlayAgainMenu;
	bool lastMenu;

        //**********************************************************************
        // Display the first menu. Redisplay if menu_selection is invalid      *
        //**********************************************************************

	//The game type menu loop.
	do
	{
		wins = 0;
		runs = 0;
		gameTypeMenu = false;
		system("cls");

			SetConsoleTextAttribute(mhConsole, 10);
		cout << "\n\t\t     Welcome to our Flood-It solver!";
			SetConsoleTextAttribute(mhConsole, 2);
		cout << "\n\n\t\tWhat type of game would you like to play?\n";
		SetConsoleTextAttribute(mhConsole, 7);
		cout << "\n\t\t\t(1) User played\n";
		cout << "\t\t\t(2) Computer Play-by-play\n";
		cout << "\t\t\t(3) Statistical driver\n\n\t\t\t>>";

		gameType = intValidationInput(3);//Checks that the user has entered an int with an upper limit of 3.

		//The play again menu loop.
		do
		{
			playAgainMenu = false;
			//Inside the play again menu is the board size menu.
			do
			{
				boardSizeMenu = false;
				system("cls");

					SetConsoleTextAttribute(mhConsole, 10);
				cout << "\n\t\t Please choose a board size:\n\n";
					 SetConsoleTextAttribute(mhConsole, 12);
				cout << "\t\t(1)\t Small Board  12x12\n";
					 SetConsoleTextAttribute(mhConsole, 2);
				cout << "\t\t(2)\t Medium Board 17x17\n";
					 SetConsoleTextAttribute(mhConsole, 14);
				cout << "\t\t(3)\t Large Board  22x22\n\n";
					SetConsoleTextAttribute(mhConsole, 13);
				cout << "\t\t(4)\t Custom Size Board\n\n";
					 SetConsoleTextAttribute(mhConsole, 7);
				cout << ">>";

				boardSelection = intValidationInput(4);//Checks that the user has entered an int with an upper limit of 4.
				boardChoice = 0;	//reset boardChoice to 0 for repeats


			//First we will convert the users board size selection into the proper size of board. 
			switch(boardSelection)
				{
				case 1:
					boardChoice = SMALL; //If they chose 1, it will become 12 for a 12x12 board.
					boardSizeMenu = true;
					break;

				case 2:
					boardChoice = MEDIUM; //If they chose 2, it will become 17 for a 17x17 board.
					boardSizeMenu = true;
					break;

				case 3:
					boardChoice = LARGE; //If they chose 3, it will become 22 for a 22x22 board.
					boardSizeMenu = true;
					break;

				case 4:				
					while(boardChoice < 1)
					{
						system("cls");
							SetConsoleTextAttribute(mhConsole, 14);
						cout << "\n\n\tPlease input a board size greater than 0. \n\n";
							SetConsoleTextAttribute(mhConsole, 8);
						cout << "\t   (i.e. For a 10x10 board, enter 10)\n";
							SetConsoleTextAttribute(mhConsole, 7);
						cout << ">>";

						boardChoice = intValidationInput(0);//Checks that the user has entered an int with no upper limit.	
					}
					boardSizeMenu = true;
					break;

				default:  
					system("cls");
				}

			}while(boardSizeMenu == false);
				
			//If they chose the statistical driver, ask for iteration count
			if(gameType == STAT_DRIVER)
			{
				int count = 0;
				SetConsoleTextAttribute(mhConsole, 7);
				cout << "\n\nHow many times would you like to iterate through the game?\n>>";
				count = intValidationInput(0);//Checks that the user has entered an int with no upper limit.

				while(count > 0)
				{
					GameBoard Board(boardChoice, gameType);	//Create the board by passing in the size
					wins += Board.GameDriver();	//And run the driver
					--count;
					++runs;
					//This is the only message the stat driver displays
					cout << endl << "You've won " << fixed << setprecision (2)
					<< 100*(double(wins)/runs) << "% of your games played.\tRuns: " << runs << " \tWins: " << wins;

				}
			}

			//Otherwise, create the board with their specifications
			else
			{			 
				GameBoard Board(boardChoice, gameType);        //Create the board by passing in the size
				wins += Board.GameDriver();
				++runs;
				cout << endl << "You've won " << fixed << setprecision (2)
				<< 100*(double(wins)/runs) << "% of your games played.\tRuns: " << runs << " \tWins: " << wins;
			}
		
			//See if they want to play the same game type again, or choose a new game type, or stop playing.
			innerPlayAgainMenu = false;
			while(innerPlayAgainMenu == false)
			{
				lastMenu = false;
				cout << endl << endl << "\n\t\tWould you like to play this game type again?\n"
					<< "\t\t\t(1) Yes\n\t\t\t(2) No\n>>";
				playAgainChoice = intValidationInput(2);//Checks that the user has entered an int with an upper limit of 2.

				if(playAgainChoice == NO)	//If not, ask if they want to choose a new game type
				{
					while(lastMenu == false)
					{
						cout << endl << endl << "\n\t\tWould you like to play a new game type?\n"
						<< "\t\t\t(1) Yes\n\t\t\t(2) No\n>>";
						playAgainChoice = intValidationInput(2);//Checks that the user has entered an int with an upper limit of 2.

						if(playAgainChoice == NO)	//If not, set every menu bool to true, which will exit the game
						{
							lastMenu = true;
							innerPlayAgainMenu = true;
							playAgainMenu = true;
							gameTypeMenu = true;
						}
						else if(playAgainChoice == YES)	//If so, set all but the gameTypeMenu to true, and it will go back to there.
						{
							lastMenu = true;
							innerPlayAgainMenu = true;
							playAgainMenu = true;
						}
						else
							;//Do nothing
					}

				}
				else if(playAgainChoice == YES)	//If they just want to play the same game again, set the innerPlayAgainMenu to true
				{								//and it will take them back to board size creation
					innerPlayAgainMenu = true;
					if(gameType == STAT_DRIVER)
					{
						wins = 0;
						runs = 0;
					}
				}
				else
					;//Do nothing
			}

		}while(playAgainMenu == false);
		
	}while(gameTypeMenu == false);
	
	return 0;
}


//IntValidationInput
//
//This function checks if the user has entered an int, and if that int is within the limits given.
//A limit of zero is an input that as no limit
//The function loops until an int meeting the conditions has been entered
//
//Pre:  An int: The limit of the input
//
//Post: Will return an int
//	
int intValidationInput(int limit)
{
	int ii = 0;
	bool validInput = false;
	bool showMessage = false;

	do
	{
		while(!(cin >> ii)) //will not accept anything that isn't an int!
		{
			showMessage = false;
			cin.clear();  //Resets the error flags in cin
	
			cin.sync();  //Resets the contents of cin to empty
	
			cout<<"Please enter a number between 1 and "<<limit<<"\n";
			showMessage = true;
		}

		validInput = true;

		//checks for a limit of 0, which allows for no upper limit
		if(limit != 0)
		{
			if(ii<1 || ii>limit)
			{
				if(showMessage == false)	//If this hasn't been shown yet, show it.
					cout<<"Please enter a number between 1 and "<<limit<<"\n";

				validInput = false;
			}
		}

	}while(validInput == false);

	cin.sync(); //clears cin when a double has been entered
	return ii;
}